home *** CD-ROM | disk | FTP | other *** search
/ Gamers Delight 2 / Gamers Delight 2.iso / Aminet / game / board / Spades.lha / Spades / Source / Play.c < prev    next >
C/C++ Source or Header  |  1992-02-03  |  17KB  |  598 lines

  1. /*
  2.    FILE: Play.c
  3.    PURPOSE: Handle the play of the hand (taking tricks)
  4.    AUTHOR: Gregory M. Stelmack
  5. */
  6.  
  7. #ifndef GLOBALS_H
  8. #include "Globals.h"
  9. #endif
  10.  
  11. /**********************************************************
  12. * Function: PlayHand                                      *
  13. * Parameters: none                                        *
  14. * Return Values: none                                     *
  15. * Purpose: Play out a hand until all 13 tricks are taken. *
  16. **********************************************************/
  17. void PlayHand()
  18. {
  19.    int i,j;
  20.    int TrickNumber;
  21.   
  22.    /* Initialize */
  23.   
  24.    PlayerTricks=CompTricks=0;
  25.    SpadePlayed=FALSE;
  26.    TrickNumber=0;
  27.    PrintTricks();
  28.    for (i=0 ; i<4 ; i++) TricksTaken[i] = 0;
  29.      
  30.    /* Loop through all 13 tricks */
  31.   
  32.    for (i=0 ; i<13 ; i++)
  33.    {
  34.       TrickLeader[i] = TrickLead;           /* Save Trick Leader */
  35.       TrickLead=TakeTrick();                /* Play a trick */
  36.       TricksTaken[TrickLead]++;
  37.       if ((TrickLead==0)||(TrickLead==2))   /* Who won? */
  38.             PlayerTricks++;
  39.       else
  40.             CompTricks++;
  41.       PrintTricks();         /* Display new trick total */
  42.       
  43.       /* Store Cards */
  44.       
  45.       for (j=0 ; j<4 ; j++)
  46.          CardPlayed[j][TrickNumber] = Card[j];
  47.       TrickNumber++;
  48.     
  49.       /* Indicate who won with an '*' */
  50.     
  51.       SetAPen(RP,YELP);
  52.       SetBPen(RP,BLUP);
  53.       Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
  54.       Text(RP,"*",1);
  55.     
  56.       /* Pause for click */
  57.  
  58.       SetAPen(RP,YELP);
  59.       Move(RP,200,150);
  60.       Text(RP,"Click mouse",11);
  61.       ReadMouse();
  62.       Move(RP,200,150);
  63.       Text(RP,"           ",11);
  64.     
  65.       /* Erase winner indicator */
  66.     
  67.       Move(RP,MsgX[TrickLead],MsgY[TrickLead]);
  68.       Text(RP," ",1);
  69.    }
  70.  
  71.    /* Store last trick winner for Save routine */
  72.    
  73.    TrickLeader[13] = TrickLead;
  74.      
  75.    /* Calculate new score */
  76.   
  77.    if (PlayerTricks<PlayerBid)
  78.          PlayerScore-=(10*PlayerBid);
  79.    if (CompTricks<CompBid)
  80.          CompScore-=(10*CompBid);
  81.    if (PlayerTricks>=PlayerBid)
  82.    {
  83.       PlayerScore+=((10*PlayerBid)+(PlayerTricks-PlayerBid));
  84.       PlayerBags+=(PlayerTricks-PlayerBid);
  85.    }
  86.    if (CompTricks>=CompBid)
  87.    {
  88.       CompScore+=((10*CompBid)+(CompTricks-CompBid));
  89.       CompBags+=(CompBags-CompBid);
  90.    }
  91.    
  92.    /* Handle Bags */
  93.    
  94.    if (BagsRule==TRUE)
  95.    {
  96.       while(PlayerBags>9)
  97.       {
  98.          PlayerScore-=100;
  99.          PlayerBags-=10;
  100.       }
  101.       while(CompBags>9)
  102.       {
  103.          CompScore-=100;
  104.          CompBags-=10;
  105.       }
  106.    }
  107.    
  108.    /* Handle Nil Bids */
  109.    
  110.    if (NilRule)
  111.    {
  112.       for (i=0 ; i<4 ; i+=2)
  113.       {
  114.          if (Bid[i]==0)
  115.          {
  116.             if (TricksTaken[i]==0)
  117.                PlayerScore+=100;
  118.             else
  119.                PlayerScore-=100;
  120.          }
  121.       }
  122.       for (i=1 ; i<4 ; i+=2)
  123.       {
  124.          if (Bid[i]==0)
  125.          {
  126.             if (TricksTaken[i]==0)
  127.                CompScore+=100;
  128.             else
  129.                CompScore-=100;
  130.          }
  131.       }
  132.    }
  133.    
  134.    /* See if hand is to be saved */
  135.    if (SaveHand == TRUE)
  136.       WriteHand();
  137.  
  138.    /* Pause for click */
  139.  
  140.    SetAPen(RP,YELP);
  141.    Move(RP,200,150);
  142.    Text(RP,"Click mouse",11);
  143.    ReadMouse();
  144.    Move(RP,200,150);
  145.    Text(RP,"           ",11);
  146. }
  147.  
  148. /**********************************************************
  149. * Function: TakeTrick                                     *
  150. * Parameters: none                                        *
  151. * Return Values: winner of trick                          *
  152. * Purpose: Each player plays a card, then determine trick *
  153. *          winner.                                        *
  154. **********************************************************/
  155. int TakeTrick()
  156. {
  157.    int i,j,leadsuit,suit,value;
  158.   
  159.    /* Clear previously played cards */
  160.   
  161.    SetAPen(RP,BLUP);
  162.    SetOPen(RP,BLUP);
  163.    for (i=0 ; i<4 ; i++)
  164.       RectFill(RP,CardX[i],CardY[i],(CardX[i]+41),(CardY[i]+41));
  165.   
  166.    /* Get played cards */
  167.   
  168.    i=TrickLead;
  169.    do
  170.    {
  171.       if (!i)
  172.             Card[i]=GetPlayerCard();
  173.       else
  174.             Card[i]=GetCompCard(i);
  175.       
  176.       if (i==TrickLead)      /* First card played wins so far */
  177.       {
  178.          HighCard=Card[i];
  179.          leadsuit=Card[i]/13;
  180.          Winner=i;
  181.       }
  182.       else
  183.       {
  184.          suit=Card[i]/13;
  185.       
  186.          /* See if this card is the new winner */
  187.       
  188.          if (((suit==leadsuit)||(suit==SPADES))&&(Card[i]>HighCard))
  189.          {
  190.             HighCard=Card[i];
  191.             Winner=i;
  192.          }
  193.       
  194.          /* Was player out of the lead suit ? */
  195.       
  196.          if (suit!=leadsuit) OutOfSuit[i][leadsuit]=TRUE;
  197.       }
  198.       i=(++i)%4;
  199.    } while (i!=TrickLead);
  200.   
  201.    ShowHand();
  202.   
  203.    /* Set highest card played in each suit */
  204.   
  205.    for (i=0 ; i<4 ; i++)
  206.    {
  207.       for (j=0 ; j<4 ; j++)    /* Need two loops to make sure we get all */
  208.       {
  209.          value=Card[j]%13;
  210.          suit=Card[j]/13;
  211.          if (value==HighCardLeft[suit]) HighCardLeft[suit]=value-1;
  212.       }
  213.    }
  214.   
  215.    /* Send back trick winner */
  216.   
  217.    return(Winner);
  218. }
  219.  
  220. /**********************************************************
  221. * Function: CountCards                                    *
  222. * Parameters: none                                        *
  223. * Return Values: none                                     *
  224. * Purpose: Count cards in each suit for a player.         *
  225. *   Determine short and long suits.                       *
  226. **********************************************************/
  227. void CountCards(player)
  228. int player;
  229. {
  230.    int i,card,suit,maximum,minimum;
  231.   
  232.    /* Initialization */
  233.   
  234.    SuitNumber[DIAMONDS]=0;
  235.    SuitNumber[CLUBS]   =0;
  236.    SuitNumber[HEARTS]  =0;
  237.    SuitNumber[SPADES]  =0;
  238.   
  239.    /* Loop through all cards in the player's hand */
  240.   
  241.    for (i=0 ; i<13 ; i++)
  242.    {
  243.       if (Hand[player][i])    /* Make sure card hasn't been played */
  244.       {
  245.          card=Hand[player][i]-1;
  246.          suit=card/13;
  247.          Value[i]=13-card;    /* Give lower cards a slight priority */
  248.          SuitNumber[suit]++;  /* Count Number of Suit held */
  249.       }
  250.       else
  251.          Value[i]=-50000;     /* Don't throw previously played cards */
  252.    }
  253.   
  254.    /* Find short and long suits */
  255.   
  256.    minimum=14;
  257.    maximum=0;
  258.    ShortSuit=LongSuit=3;
  259.    for (i=DIAMONDS ; i<SPADES ; i++)
  260.    {
  261.       if ((SuitNumber[i]<minimum)&&(SuitNumber[i]>0))
  262.       {
  263.          minimum=SuitNumber[i];
  264.          ShortSuit=i;
  265.       }
  266.       if (SuitNumber[i]>maximum)
  267.       {
  268.          maximum=SuitNumber[i];
  269.          LongSuit=i;
  270.       }
  271.    }
  272. }
  273.   
  274. /**********************************************************
  275. * Function: SuggestCard                                   *
  276. * Parameters: none                                        *
  277. * Return Values: none                                     *
  278. * Purpose: Suggest a card for player to play.             *
  279. **********************************************************/
  280. void SuggestCard()
  281. {
  282.    int i,pick,maximum;
  283.   
  284.    CountCards(0);
  285.  
  286.    /* Go to appropriate point calculating routine */
  287.   
  288.    if (!TrickLead)
  289.          CalcLead(0);
  290.    else
  291.          CalcFollow(0);
  292.   
  293.    /* Find best card (the one with the most points) */
  294.   
  295.    pick=0;
  296.    maximum=Value[0];
  297.    for (i=1 ; i<13 ; i++)
  298.    {
  299.       if (Value[i]>maximum)
  300.       {
  301.          maximum=Value[i];
  302.          pick=i;
  303.       }
  304.    }
  305.   
  306.    /* Display an '*' over suggested card */
  307.   
  308.    SetAPen(RP,YELP);
  309.    SetBPen(RP,BLUP);
  310.    Move(RP,((pick*10))+22,142);
  311.    Text(RP,"*",1);
  312. }
  313.  
  314. /**********************************************************
  315. * Function: GetCompCard                                   *
  316. * Parameters: player -- player to play                    *
  317. * Return Values: card played                              *
  318. * Purpose: Determine which card a computer-controlled     *
  319. *   player will play.                                     *
  320. **********************************************************/
  321. int GetCompCard(player)
  322. int player;
  323. {
  324.    int i,pick,card,maximum;
  325.   
  326.    CountCards(player);
  327.  
  328.    /* Go to appropriate point calculating routine */
  329.   
  330.    if (player==TrickLead)
  331.          CalcLead(player);
  332.    else
  333.          CalcFollow(player);
  334.   
  335.    /* Find best card (the one with the most points) */
  336.   
  337.    pick=0;
  338.    maximum=Value[0];
  339.    for (i=1 ; i<13 ; i++)
  340.    {
  341.       if (Value[i]>maximum)
  342.       {
  343.          maximum=Value[i];
  344.          pick=i;
  345.       }
  346.    }
  347.   
  348.    card=Hand[player][pick]-1;
  349.    if ((card/13)==3)       /* Mark that spades have been broken */
  350.          SpadePlayed = TRUE;
  351.    Hand[player][pick]=0;   /* Card has now been played */
  352.    DrawCard(CardX[player],CardY[player],card);  /* Draw the played card */
  353.    return(card);           /* Send the played card back */
  354. }
  355.  
  356. /**********************************************************
  357. * Function: CalcLead                                      *
  358. * Parameters: player -- whose hand to calculate           *
  359. * Return Values: none                                     *
  360. * Purpose: To calculate the value of each card in a hand  *
  361. *          to determine which card should be played if    *
  362. *          the hand is leading.                           *
  363. **********************************************************/
  364. void CalcLead(player)
  365. int player;
  366. {
  367.    int i,card,suit,value;
  368.    BOOL opponentsout=FALSE, partnerout=FALSE;
  369.    BOOL WantToTake=FALSE;
  370.    
  371.    /* See if we want to take this trick */
  372.    
  373.    WantToTake = FigureTake(player);
  374.    
  375.    /* Loop through all cards in hand */
  376.   
  377.    for (i=0 ; i<13 ; i++)
  378.    {
  379.       if (Hand[player][i])   /* Make sure card hasn't been played */
  380.       {
  381.          /* Find suit and face value */
  382.       
  383.          card=Hand[player][i]-1;
  384.          suit=card/13;
  385.          value=card%13;
  386.       
  387.          if ((OutOfSuit[(player+1)%4][suit])||
  388.              (OutOfSuit[(player+3)%4][suit]))
  389.                opponentsout=TRUE;
  390.         
  391.          if (OutOfSuit[(player+2)%4][suit])
  392.                partnerout=TRUE;
  393.       
  394.          if (value==HighCardLeft[suit]) /* Card is highest left in a suit */
  395.          {
  396.             if (!WantToTake)  /* Don't throw high card if we don't want to
  397.                                  take. */
  398.                   Value[i]-=100;
  399.             else
  400.             {
  401.                if (suit==SPADES)    /* Spades don't matter if someone is */
  402.                   Value[i]+=50;     /* out. */
  403.                else
  404.                {  
  405.                   /* If opponents are out (or likely to be), don't waste */
  406.                   if ((opponentsout)||(value<11))     /* high cards.     */
  407.                        Value[i]-=50;
  408.                   else
  409.                         Value[i]+=500;
  410.                }  
  411.             }
  412.          }
  413.       
  414.          /* If player holds spades, get rid of short suit */
  415.          if ((SuitNumber[SPADES])&&(suit==ShortSuit)) Value[i]+=250;
  416.       
  417.          /* If player doesn't hold spades, get rid of long suit */
  418.          if ((!SuitNumber[SPADES])&&(suit==LongSuit)) Value[i]+=250;
  419.       
  420.          /* If spades aren't broken, they can't be lead */
  421.          if ((suit==SPADES)&&(!SpadePlayed)) Value[i]-=5000;
  422.       
  423.          /* Lead suits your partner is out of */
  424.          if ((suit!=SPADES)&&(partnerout)&&(!opponentsout)) Value[i]+=100;
  425.       }
  426.    }
  427. }
  428.  
  429. /**********************************************************
  430. * Function: CalcFollow                                    *
  431. * Parameters: player -- whose hand to calculate           *
  432. * Return Values: none                                     *
  433. * Purpose: To calculate the value of each card in a hand  *
  434. *          to determine which card should be played if    *
  435. *          the hand is not leading.                       *
  436. **********************************************************/
  437. void CalcFollow(player)
  438. int player;
  439. {
  440.    int i,card,suit,value,leadsuit;
  441.    BOOL alreadywon,WantToTake,PartnerTake;
  442.   
  443.    leadsuit=Card[TrickLead]/13;  /* Calculate the suit that was lead */
  444.   
  445.    /* See if partner has already won the trick */
  446.   
  447.    alreadywon=FALSE;
  448.    
  449.    /* See if win is guaranteed (player is last to play) */
  450.    if ((Winner==((player+2)%4))&&(TrickLead==((player+1)%4)))
  451.          alreadywon=TRUE;  
  452.     
  453.    /* See if win is probable (player is next to last to play) */
  454.    if ((Winner==TrickLead)&&(TrickLead==((player+2)%4)))
  455.    {
  456.       value=Card[TrickLead]%13;
  457.       if ((value==HighCardLeft[leadsuit])&&(value>9)&&
  458.          !OutOfSuit[(player+3)%4][leadsuit])
  459.             alreadywon=TRUE;
  460.    }
  461.    
  462.    /* See if we want to take the trick */
  463.    
  464.    WantToTake = FigureTake(player);
  465.    
  466.    /* See if partner should take trick */
  467.    
  468.    PartnerTake = FigureTake((player+2)%4);
  469.    
  470.    /* If our partner has taken the trick so far, but shouldn't, set the
  471.       alreadywon flag to FALSE so that we can try to take the trick */
  472.       
  473.    if ((alreadywon==TRUE)&&(PartnerTake==FALSE))
  474.          alreadywon=FALSE;
  475.  
  476.    /* Loop through all cards in hand */
  477.   
  478.    for (i=0 ; i<13 ; i++)
  479.    {
  480.       if (Hand[player][i])  /* Make sure card hasn't been played */
  481.       {
  482.          /* Find suit and face value of card */
  483.       
  484.          card=Hand[player][i]-1;
  485.          suit=card/13;
  486.          value=card%13;
  487.       
  488.          if (suit==leadsuit)   /* Card is of lead suit */
  489.          { 
  490.             Value[i]+=5000;
  491.         
  492.             /* If it is the highest one left in that suit, and we want to
  493.                take the trick, throw it. */
  494.             if ((value==HighCardLeft[suit])&&
  495.                 (TrickLead!=((player+1)%4))&&
  496.                 (card>HighCard)&&!OutOfSuit[(player+1)%4][suit]&&
  497.                 (WantToTake==TRUE)&&
  498.                 (alreadywon==FALSE))
  499.             {
  500.                   Value[i]+=70;
  501.             }
  502.           
  503.             /* See if card will beat those previously played */
  504.             if (card>HighCard)
  505.             {
  506.                /* If we don't want to take, or our partner has it, DON'T */
  507.                if ((WantToTake==FALSE)||(alreadywon==TRUE))
  508.                      Value[i]-=500;
  509.                else
  510.                      Value[i]+=100;
  511.             }
  512.         
  513.             /* If we don't want to win, throw low cards */
  514.             if ((card<HighCard)&&((WantToTake==FALSE)||(alreadywon==TRUE)))
  515.                   Value[i]+=75;
  516.          }
  517.       
  518.          /* If player is going to throw a spade, make sure it has
  519.             a chance of winning (and that we want to take it */
  520.          if ((suit==SPADES)&&(card>HighCard))
  521.          {
  522.             if ((WantToTake==TRUE)&&(alreadywon==FALSE))
  523.                   Value[i]+=100; /* If team hasn't won, throw the spade */
  524.             else
  525.                   Value[i]-=1000; /* If team has won, hold high spades */
  526.          }
  527.          if ((suit==SPADES)&&(card<HighCard))
  528.          {
  529.             if (WantToTake==FALSE)
  530.                   Value[i]+=1000;   /* If we don't want to take trick,
  531.                                       get rid of Spades */
  532.             else
  533.                   Value[i]-=500;    /* Don't waste a Spade */
  534.          }
  535.       
  536.          /* If player is out of the lead suit, don't throw important cards
  537.             in other suits (unless we don't want to take) */
  538.          if ((suit!=leadsuit)&&(value==HighCardLeft[suit]))
  539.          {
  540.             if (WantToTake==FALSE)
  541.                Value[i]+=500;
  542.             else
  543.                Value[i]-=100;
  544.          }
  545.       
  546.          /* If player is out of lead suit, let's see about trumping */
  547.          if ((!SuitNumber[leadsuit])&&(suit==SPADES))
  548.          {
  549.             if ((WantToTake==TRUE)&&(alreadywon==FALSE))
  550.                   Value[i]+=100;  /* If team hasn't won, trump */
  551.             else
  552.                   Value[i]-=1000; /* If team has won, no need to trump */
  553.          }
  554.       
  555.          /* If player is out of lead suit and out of spades, throw the long
  556.             suit left (keep as many suits as possible in hand) */
  557.          if ((!SuitNumber[leadsuit])&&
  558.              (!SuitNumber[SPADES])&&
  559.              (suit==LongSuit))
  560.          {
  561.             Value[i]+=100;
  562.          }
  563.       
  564.          /* Give short suit a priority */
  565.          if (suit==ShortSuit) Value[i]+=45;
  566.       }
  567.    }
  568. }
  569.  
  570. /*************************************************
  571. * Function: FigureTake                           *
  572. * Parameters: player -- player to deal with.     *
  573. * Return Values: BOOL -- TRUE if player should   *
  574. *     try to take trick.                         *
  575. * Purpose: See if a player should take or give a *
  576. *     trick.                                     *
  577. *************************************************/
  578. BOOL FigureTake(player)
  579. int player;
  580. {
  581.    BOOL ShouldTake;
  582.    
  583.    ShouldTake = TRUE;
  584.    
  585.    if ((NilRule==TRUE)&&(Bid[player]==0))
  586.          ShouldTake = FALSE;
  587.    else
  588.    {
  589.       if ((TricksTaken[player]+TricksTaken[(player+2)%4]) <
  590.           (Bid[player]+Bid[(player+2)%4]))
  591.             ShouldTake = TRUE;
  592.       else if (BagsRule==TRUE)
  593.             ShouldTake = FALSE;
  594.    }
  595.    
  596.    return(ShouldTake);
  597. }
  598.